package binarycrew.livewallpapers;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.os.AsyncTask;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import binarycrew.livewallpapers.helpers.Http;
import binarycrew.livewallpapers.utils.PreferenceHelper;
import binarycrew.livewallpapers.utils.WallpapersDatabase;
import binarycrew.livewallpapers.wallpapers.ALiveWallpaper;
import binarycrew.livewallpapers.wallpapers.Wallpapers;

public class LiveWallpaper extends WallpaperService {

	private final Handler mHandler = new Handler();
	//private final Handler downloadHandler = new Handler();
	private final int loadNewGalleryTimeout = 60 * 60 * 1000; // once per hour

	@Override
	public void onCreate() {
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public Engine onCreateEngine() {
		String wallpaperCode;

		SharedPreferences settings = getSharedPreferences("LiveWallpapers", 0);
		wallpaperCode = settings.getString("wallpaper", "photo_wallpaper");

		return new WallpaperEngine(
				Wallpapers.findWallpaperByCode(wallpaperCode));
	}

	class WallpaperEngine extends Engine {

		public static final String TAG = "WallpaperEngine";

		private final ALiveWallpaper liveWallpaper;

		private final Runnable mDrawWallpaper = new Runnable() {

			@Override
			public void run() {
				drawFrame();
			}
		};

		private final Runnable downloadImagesFromWeb = new Runnable() {

			@Override
			public void run() {
				new AsyncDownload().execute();
			}
		};

		private boolean mVisible;

		WallpaperEngine(ALiveWallpaper wallpaper) {
			this.liveWallpaper = wallpaper;
		}

		@Override
		public void onCreate(SurfaceHolder surfaceHolder) {
			super.onCreate(surfaceHolder);

			downloadImagesFromWeb.run();

			// By default we don't get touch events, so enable them.
			//setTouchEventsEnabled(true);
		}

		@Override
		public void onDestroy() {
			super.onDestroy();
			mHandler.removeCallbacks(mDrawWallpaper);
			mHandler.removeCallbacks(downloadImagesFromWeb);
		}

		@Override
		public void onVisibilityChanged(boolean visible) {
			mVisible = visible;
			if (visible) {
				drawFrame();
			}
			else {
				mHandler.removeCallbacks(mDrawWallpaper);
			}
		}

		@Override
		public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
			super.onSurfaceChanged(holder, format, width, height);
			this.liveWallpaper.setScreenSize(width, height);
			drawFrame();
		}

		@Override
		public void onSurfaceCreated(SurfaceHolder holder) {
			super.onSurfaceCreated(holder);
		}

		@Override
		public void onSurfaceDestroyed(SurfaceHolder holder) {
			super.onSurfaceDestroyed(holder);
			mVisible = false;
			mHandler.removeCallbacks(mDrawWallpaper);
		}

		@Override
		public void onOffsetsChanged(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels) {
			drawFrameOnOffsetsChanged(xOffset, yOffset, xStep, yStep, xPixels, yPixels);
		}

		@Override
		public void onTouchEvent(MotionEvent event) {
		}

		public void drawFrame() {
			final SurfaceHolder holder = getSurfaceHolder();

			Canvas c = null;
			try {
				c = holder.lockCanvas();
				if (c != null) {
					liveWallpaper.drawCanvas(c);
				}
			}
			finally {
				if (c != null)
					holder.unlockCanvasAndPost(c);
			}

			// Reschedule the next redraw
			mHandler.removeCallbacks(mDrawWallpaper);
			if (mVisible) {
				mHandler.postDelayed(mDrawWallpaper, (int) (1000 / liveWallpaper.getFPS()));
			}
		}

		void drawFrameOnOffsetsChanged(float xOffset, float yOffset,
				float xStep, float yStep, int xPixels, int yPixels) {
			final SurfaceHolder holder = getSurfaceHolder();

			Canvas c = null;
			try {
				c = holder.lockCanvas();
				if (c != null) {
					liveWallpaper.drawCanvasOnOffsetsChanged(c, xOffset, yOffset, xStep, yStep, xPixels, yPixels);
				}
			}
			finally {
				if (c != null)
					holder.unlockCanvasAndPost(c);
			}

			// Reschedule the next redraw
			mHandler.removeCallbacks(mDrawWallpaper);
			if (mVisible) {
				mHandler.postDelayed(mDrawWallpaper, (int) (1000 / liveWallpaper.getFPS()));
			}
		}

		private class AsyncDownload extends AsyncTask<Void, Void, Void> {

			private Boolean wasWallpaperDisplayed = false;

			private String selectRandomGalerySource() {
				String[] source_urls =
						PreferenceHelper.getSourceUrls(getSharedPreferences(Preferences.SHARED_PREFS_NAME, 0));

				if (source_urls.length == 0) { return Preferences.DEFAULT_SOURCE_URL; }

				int pos = (int) (Math.random() * source_urls.length);
				return source_urls[pos];
			}

			@Override
			protected Void doInBackground(Void... urls) {
				String gallery_source = selectRandomGalerySource();

				String html = Http.read(gallery_source);//"http://www.sme.sk/r/online_foto/press_foto.html"
				Document mainPage = Jsoup.parse(html);
				Elements links = mainPage.select(".perexw td a[href]");

				String detailUrl = "";
				for (int i = 0; i < links.size(); i++) {
					int pos = (int) (Math.random() * links.size());
					detailUrl = links.get(pos).attr("href");

					if (WallpapersDatabase.getInstance(getApplicationContext()).containsGallery(detailUrl)) {
						Log.d(TAG, "already downloaded gallery: " + detailUrl);
					}
					else {
						break;
					}
				}

				boolean result = false;
				String htmlGallery = Http.read(detailUrl);

                if(htmlGallery != null) {
                    Document galleryPage = Jsoup.parse(htmlGallery);
                    Elements galleryImages = galleryPage.select(".cl-fotorub img[src]");

                    for (Element element : galleryImages)
                        result |= Http.DownloadImageFromUrl(element, Preferences.getFilesDir());

                    publishProgress();

                    if (result == true) {
                        WallpapersDatabase.getInstance(getApplicationContext()).insertGallery(detailUrl);
                    }
                } else {
                    // TODO: load other gallery if failed
                }

				return null;
			}

			@Override
			protected void onProgressUpdate(Void... progress) {
				if (!wasWallpaperDisplayed) {
					drawFrame();
					wasWallpaperDisplayed = true;
				}
			}

			@Override
			protected void onPostExecute(Void result) {
				mHandler.postDelayed(downloadImagesFromWeb, loadNewGalleryTimeout);
			}
		}
	}
}
